package com.hyt.it.ogt.ykcj.service.exam.impl;

import com.hyt.it.ogt.ykcj.common.core.redis.RedisCache;
import com.hyt.it.ogt.ykcj.common.enums.CommonEnums;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.domain.vo.ExamInfoVo;
import com.hyt.it.ogt.ykcj.feign.model.Classification;
import com.hyt.it.ogt.ykcj.feign.model.ResultObjEntity;
import com.hyt.it.ogt.ykcj.feign.pt.PtClient;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamInfoMapper;
import com.hyt.it.ogt.ykcj.service.exam.IClassificationService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * description 考试分类Service接口
 *
 * @author yaojian
 * @createTime 2022/02/14
 */
@Service
public class ClassificationServiceImpl implements IClassificationService {

    private static final Logger log = LoggerFactory.getLogger(ClassificationServiceImpl.class);
    @Autowired
    private PtClient signUpClient;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ExamInfoMapper examInfoMapper;

    @Override
    public List<Classification> getClassificationTree(String other) {
        List<Classification> classificationList = this.getBaseClassificationTree();
        sort(classificationList);
        if (CommonEnums.EXAMTYPE_SHOW_OTHER_1.getCode().equals(other)) {
            Classification Class = new Classification();
            Class.setId(CommonEnums.EXAM_TYPE_OTHER.getCode());
            Class.setName(CommonEnums.EXAM_TYPE_OTHER.getDesc());
            Class.setExaminationId(CommonEnums.EXAM_TYPE_OTHER.getCode());
            Class.setChildren(new ArrayList<>());
            Class.setParentId("0");
            Class.setCategorylevel(0);
            classificationList.add(Class);
        }
        return classificationList;
    }

    public List<Classification> getClassificationList() {
        List<Classification> tree = this.getBaseClassificationTree();
        List<Classification> classificationList = new ArrayList<>();
        for (Classification classification : tree) {
            classificationList.addAll(getList(classification));
        }
        sort(classificationList);
        //显示其他
        Classification Class = new Classification();
        Class.setId(CommonEnums.EXAM_TYPE_OTHER.getCode());
        Class.setName(CommonEnums.EXAM_TYPE_OTHER.getDesc());
        Class.setExaminationId(CommonEnums.EXAM_TYPE_OTHER.getCode());
        Class.setChildren(new ArrayList<>());
        Class.setParentId("0");
        Class.setCategorylevel(0);
        classificationList.add(Class);
        return classificationList;
    }

    @Override
    public List<Classification> getChildList(String id) {
        //定义树节点
        Classification classificationTree = new Classification();
        //获取所有的list
        List<Classification> allClass = getClassificationList();
        //设置父子关系
        setParentChild(allClass);
        //
        for (Classification cla : allClass) {
            if (cla.getId().equals(id)) {
                classificationTree = cla;
                break;
            }
        }
        //获取这颗树的list数据
        List<Classification> classificationList = getList(classificationTree);
        return classificationList;
    }

    @Override
    public List<Classification> getHasNodeTree(String officeId) {
        //查询到数据库中存在的考试类型
        List<ExamInfoVo> classficationIdList = examInfoMapper.getClassficationId(officeId);
        List<Classification> classificationList = getBaseClassificationList();
        //定义存放list数据
        List<Classification> exitList = new ArrayList<>();
        //把所有的存在的节点的数据及父节点的数据查询到exitList中
        for (ExamInfoVo tempExamInfo : classficationIdList) {
            Classification byId = getById(tempExamInfo.getExamType(), classificationList);
            if (byId.getParentId() != null) {
                exitList.addAll(getParentList(byId, exitList, classificationList));
            }
        }

        List<Classification> parentAndMeList = new ArrayList<Classification>(new LinkedHashSet<Classification>(exitList));
        //把list数据转化为树形结构数据
        List<Classification> tree = getTree(parentAndMeList);
        sort(tree);
        //显示其他
        Classification Class = new Classification();
        Class.setId(CommonEnums.EXAM_TYPE_OTHER.getCode());
        Class.setName(CommonEnums.EXAM_TYPE_OTHER.getDesc());
        Class.setExaminationId(CommonEnums.EXAM_TYPE_OTHER.getCode());
        Class.setChildren(new ArrayList<>());
        Class.setParentId("0");
        Class.setCategorylevel(0);
        tree.add(Class);
        return tree;
    }

    /**
     * 获取list数据
     *
     * @return
     */
    public List<Classification> getBaseClassificationList() {
        List<Classification> tree = this.getBaseClassificationTree();
        List<Classification> classificationList = new ArrayList<>();
        for (Classification classification : tree) {
            classificationList.addAll(getList(classification));
        }
        return classificationList;
    }

    /**
     * 获取基础的分类数据
     *
     * @return
     */
    private List<Classification> getBaseClassificationTree() {
        ResultObjEntity<Classification> resultObjEntity = redisCache.getCacheObject("cachegetClassificationTreeKey");
        if (resultObjEntity == null) {
            resultObjEntity = signUpClient.getTreelist();
            redisCache.setCacheObject("cachegetClassificationTreeKey", resultObjEntity, 20, TimeUnit.MINUTES);
        }
        if (resultObjEntity.getCode() == Integer.parseInt(CommonEnums.PT_REQUEST_SUCCESS.getCode())) {
            List<Classification> classificationList = resultObjEntity.getData().getChildren();
            return classificationList;
        } else {
            throw new CustomException("无法获取考试类型！");
        }
    }

    /**
     * 把树形结构该成list结构
     *
     * @param classification
     * @return
     */
    private List<Classification> getList(Classification classification) {
        List<Classification> classificationList = new ArrayList<>();
        Classification classica = new Classification();
        try {
            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
            BeanUtils.copyProperties(classica, classification);
            classica.setChildren(null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        classificationList.add(classica);
        if (classification.getChildren() != null && classification.getChildren().size() > 0) {
            for (Classification child : classification.getChildren()) {
                classificationList.addAll(getList(child));
            }
        }
        return classificationList;
    }

    /**
     * 根据父节点获取全部子节点
     *
     * @param id
     * @param nodeList
     * @return
     */
    @Override
    public List<String> getChildrenId(String id, List<Classification> nodeList) {
        List<String> resultList = new ArrayList<>();
        resultList.add(id);
        if (CollectionUtils.isEmpty(nodeList)) {
            //获取所有的list
            nodeList = getClassificationList();
        }
        Map<String, String> examinationIdMap = nodeList.stream().filter(c -> StringUtils.isNotEmpty(c.getExaminationId())).collect(Collectors.toMap(Classification::getId, Classification::getExaminationId, (key1, key2) -> key2));
        //根据id获取examinationId
        if (null == examinationIdMap.get(id)) {
            return resultList;
        }
        try {
            for (Classification layer : nodeList) {
                if (examinationIdMap.get(id).equals(layer.getParentId())) {
                    //添加子级节点
                    resultList.add(layer.getId());
                    //递归获取深层节点
                    resultList.addAll(getChildrenId(layer.getExaminationId(), nodeList));
                }
            }

        } catch (Exception e) {
            log.error("根据父节点获取全部子节点getChildrenId方法异常:{}", e);
        }

        return resultList;
    }

    /**
     * 获取树节点
     *
     * @param allNode
     * @return
     */
    public static List<Classification> getTree(List<Classification> allNode) {
        List<Classification> treeList = new ArrayList<>();
        //构造所有的对象
        for (Classification node : allNode) {
            judgeNode(node, allNode);
        }
        //把构造好子节点的添加到list中
        for (Classification node : allNode) {
            if (node.getParentId().equals("0")) {
                treeList.add(node);
            }
        }
        return treeList;
    }

    /**
     * 把树的节点添加到child中
     *
     * @param node
     * @param allNode
     */
    public static void judgeNode(Classification node, List<Classification> allNode) {
        for (Classification temp : allNode) {
            if (temp.getParentId().equals(node.getExaminationId())) {
                List<Classification> childList = node.getChildren();
                if (childList == null) {
                    childList = new ArrayList<>();
                }
                childList.add(temp);
                node.setChildren(childList);
            }
        }
    }

    /**
     * 获取自己及父节点的数据
     *
     * @param node
     * @param newList
     * @param allList
     * @return
     */
    public static List<Classification> getParentList(Classification node, List<Classification> newList, List<Classification> allList) {
        if (node.getParentId().equals("0")) {
            Classification newNode = new Classification();
            newNode.setId(node.getId());
            newNode.setParentId(node.getParentId());
            newNode.setExaminationId(node.getExaminationId());
            newNode.setName(node.getName());
            newList.add(newNode);
            return newList;
        } else {
            Classification newNode = new Classification();
            newNode.setId(node.getId());
            newNode.setParentId(node.getParentId());
            newNode.setExaminationId(node.getExaminationId());
            newNode.setName(node.getName());
            newList.add(newNode);
            List<Classification> parentList = getParentList(getByExaminationId(node.getParentId(), allList), newList, allList);
            return parentList;
        }
    }

    /**
     * 根据id获取节点内容
     *
     * @param id
     * @param allNodeList
     * @return
     */
    private static Classification getById(String id, List<Classification> allNodeList) {
        Classification newNode = new Classification();
        for (Classification node : allNodeList) {
            if (node.getId().equals(id)) {
                newNode.setId(node.getId());
                newNode.setParentId(node.getParentId());
                newNode.setExaminationId(node.getExaminationId());
                newNode.setName(node.getName());
                break;
            }
        }
        return newNode;
    }

    /**
     * 根据id获取节点内容
     *
     * @param examinationId
     * @param allNodeList
     * @return
     */
    private static Classification getByExaminationId(String examinationId, List<Classification> allNodeList) {
        Classification newNode = new Classification();
        for (Classification node : allNodeList) {
            if (node.getExaminationId() != null && node.getExaminationId().equals(examinationId)) {
                newNode.setId(node.getId());
                newNode.setParentId(node.getParentId());
                newNode.setExaminationId(node.getExaminationId());
                newNode.setName(node.getName());
                break;
            }
        }
        return newNode;
    }

    /**
     * 设置子类
     *
     * @param allList
     * @return
     */
    public void setParentChild(List<Classification> allList) {
        for (Classification cla : allList) {
            for (Classification setCla : allList) {
                if (cla.getExaminationId() != null && cla.getExaminationId().equals(setCla.getParentId())) {
                    List<Classification> children = cla.getChildren();
                    if (children != null) {
                        children.add(setCla);
                        cla.setChildren(children);
                    } else {
                        children = new ArrayList<>();
                        children.add(setCla);
                        cla.setChildren(children);
                    }
                }
            }
        }
    }

    /**
     * 对树进行排序
     *
     * @param classificationTree
     * @return
     */
    private List<Classification> sort(List<Classification> classificationTree) {
        for (Classification classification : classificationTree) {
            if (classification.getChildren() != null && classification.getChildren().size() > 0) {
                sort(classification.getChildren());
            }
        }
        Collections.sort(classificationTree, new Comparator<Classification>() {
            @Override
            public int compare(Classification o1, Classification o2) {
                return o1.getName().compareToIgnoreCase(o2.getName());
            }
        });
        return classificationTree;
    }

}
